#include "./../inc/ai_snake.h"
#include <iostream>
#include <random>

AISnake *AISnake::m_instance = nullptr;

AISnake::~AISnake() { clearAISnake(); }

void AISnake::init(int x, int y)
{
    m_snakeBody.clear();
    m_snakeBody.push_back(Point((x * GRID_SIZE) + MAP_START_X, y * GRID_SIZE));
    m_snakeBody.push_back(Point(((x - 1) * GRID_SIZE) + MAP_START_X, y * GRID_SIZE));
    show();
}

void AISnake::show()
{
    if (m_snakeBody.empty())
        return;

    for (auto &i : m_snakeBody)
    {
        if (i == m_snakeBody.front())
        {
            switch (direction)
            {
            case UP:
                head_up.showIcon(mp, i.x(), i.y());
                break;
            case DOWN:
                head_down.showIcon(mp, i.x(), i.y());
                break;
            case LEFT:
                head_left.showIcon(mp, i.x(), i.y());
                break;
            case RIGHT:
                head_right.showIcon(mp, i.x(), i.y());
                break;
            }
            continue;
        }
        else if (i == m_snakeBody.back())
        {
            auto it = m_snakeBody.end();
            --it;
            --it;
            Point prev = *it;

            if (prev.y() < i.y())
                tail_up.showIcon(mp, i.x(), i.y());
            else if (prev.y() > i.y())
                tail_down.showIcon(mp, i.x(), i.y());
            else if (prev.x() < i.x())
                tail_left.showIcon(mp, i.x(), i.y());
            else if (prev.x() > i.x())
                tail_right.showIcon(mp, i.x(), i.y());
            continue;
        }
        body.show(mp, i.x(), i.y());
    }
}
bool AISnake::move()
{
    if (m_snakeBody.empty() || !playerSnake)
        return false;

    decideDirection();

    Point newHead = calculateNewHead();
    if (isCollision(newHead))
    {
        clearAISnake();
        return false; // 碰撞后不再移动
    }
    handleMovement(newHead);
    return true;
}

void AISnake::clearAISnake()
{
    // 碰撞后处理：清空蛇身并清理地图上的AI蛇痕迹
    while (!m_snakeBody.empty())
    {
        Point segment = m_snakeBody.back();
        int row = segment.y() / GRID_SIZE;
        int col = (segment.x() - MAP_START_X) / GRID_SIZE;

        // 清理地图标记
        m_map->getGrid()[row][col] = GRID_EMPTY;
        // 清理显示（用背景覆盖）
        m_map->getMap().local_show(mp, segment.x(), segment.y(),
                                   segment.x() - MAP_START_X, segment.y(),
                                   GRID_SIZE, GRID_SIZE);

        m_snakeBody.pop_back();
    }
}

Point AISnake::calculateNewHead()
{
    Point head = m_snakeBody.front();
    int newX = head.x();
    int newY = head.y();

    switch (direction)
    {
    case UP:
        newY -= GRID_SIZE;
        break;
    case DOWN:
        newY += GRID_SIZE;
        break;
    case LEFT:
        newX -= GRID_SIZE;
        break;
    case RIGHT:
        newX += GRID_SIZE;
        break;
    }

    return Point(newX, newY);
}

bool AISnake::isCollision(const Point &newHead)
{
    int newX = newHead.x();
    int newY = newHead.y();

    // 撞墙检测
    if (newX < MAP_START_X || newX >= MAP_START_X + MAP_WIDTH ||
        newY < 0 || newY >= MAP_HEIGHT)
        return true;

    // 撞自身检测
    int headRow = newY / GRID_SIZE;
    int headCol = (newX - MAP_START_X) / GRID_SIZE;
    GridState state = static_cast<GridState>(m_map->getGrid()[headRow][headCol]);

    // 撞到玩家蛇（GRID_SNAKE_BODY）或自身（GRID_AI_SNAKE_BODY）都算碰撞
    return (state == GRID_SNAKE_BODY || state == GRID_AI_SNAKE_BODY);
}

void AISnake::handleMovement(const Point &newHead)
{
    int newX = newHead.x();
    int newY = newHead.y();
    int headRow = newY / GRID_SIZE;
    int headCol = (newX - MAP_START_X) / GRID_SIZE;

    GridState newPosType = static_cast<GridState>(m_map->getGrid()[headRow][headCol]);
    bool ateFood = handleFood(newPosType);

    // 更新蛇头显示（旧头变身体）
    body.show(mp, m_snakeBody.front().x(), m_snakeBody.front().y());
    m_snakeBody.push_front(newHead);
    m_map->getGrid()[headRow][headCol] = GRID_AI_SNAKE_BODY;

    if (!ateFood)
    {
        removeTail();
    }
    else
    {
        m_map->generateRandomFood();
    }

    // 绘制新蛇头
    switch (direction)
    {
    case UP:
        head_up.showIcon(mp, newX, newY);
        break;
    case DOWN:
        head_down.showIcon(mp, newX, newY);
        break;
    case LEFT:
        head_left.showIcon(mp, newX, newY);
        break;
    case RIGHT:
        head_right.showIcon(mp, newX, newY);
        break;
    }

    // 更新蛇尾显示
    if (m_snakeBody.size() >= 2)
    {
        auto it = m_snakeBody.end();
        --it;
        Point tail = *it;
        --it;
        Point prev = *it;
        m_map->getMap().local_show(mp, tail.x(), tail.y(), tail.x() - MAP_START_X, tail.y(), GRID_SIZE, GRID_SIZE);
        if (prev.y() < tail.y())
            tail_up.showIcon(mp, tail.x(), tail.y());
        else if (prev.y() > tail.y())
            tail_down.showIcon(mp, tail.x(), tail.y());
        else if (prev.x() < tail.x())
            tail_left.showIcon(mp, tail.x(), tail.y());
        else if (prev.x() > tail.x())
            tail_right.showIcon(mp, tail.x(), tail.y());
    }
}

bool AISnake::handleFood(GridState foodType)
{
    if (foodType != GRID_EMPTY && foodType != GRID_FOOD_BOMB)
    {
        m_map->getFoodCount()--;
    }

    switch (foodType)
    {
    case GRID_FOOD_SCORE_1:
        return true;
    case GRID_FOOD_SCORE_2:
        return true;
    case GRID_FOOD_SPEED_UP:
        return true;
    case GRID_FOOD_SPEED_DOWN:
        return true;
    case GRID_FOOD_BOMB:
        return true;
    default:
        return false;
    }
}

void AISnake::removeTail()
{
    Point tail = m_snakeBody.back();
    int tailRow = tail.y() / GRID_SIZE;
    int tailCol = (tail.x() - MAP_START_X) / GRID_SIZE;

    m_map->getMap().local_show(mp, tail.x(), tail.y(), tail.x() - MAP_START_X, tail.y(), GRID_SIZE, GRID_SIZE);
    m_map->getGrid()[tailRow][tailCol] = GRID_EMPTY;
    m_snakeBody.pop_back();
}

// AI决策逻辑（基于玩家蛇信息）
void AISnake::decideDirection()
{
    if (!playerSnake)
        return;

    // 获取玩家蛇头位置（通过玩家蛇实例直接获取）
    Point playerHead = playerSnake->getHeadPosition();

    Point aiHead = m_snakeBody.front();
    int aiX = aiHead.x();
    int aiY = aiHead.y();
    int playerX = playerHead.x();
    int playerY = playerHead.y();

    // 优先横向追踪玩家蛇头
    if (playerX > aiX && direction != LEFT)
    {
        direction = RIGHT;
        return;
    }
    if (playerX < aiX && direction != RIGHT)
    {
        direction = LEFT;
        return;
    }

    // 横向对齐后纵向追踪
    if (playerY > aiY && direction != UP)
    {
        direction = DOWN;
        return;
    }
    if (playerY < aiY && direction != DOWN)
    {
        direction = UP;
        return;
    }

    // 无法直接追踪时随机移动（避免反向）
    static std::random_device rd;
    static std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 4);

    int newDir;
    do
    {
        newDir = dis(gen);
    } while (
        (direction == UP && newDir == DOWN) ||
        (direction == DOWN && newDir == UP) ||
        (direction == LEFT && newDir == RIGHT) ||
        (direction == RIGHT && newDir == LEFT));

    direction = newDir;
}

AISnake *AISnake::instance(int *mp, Snake *snake, GameMap *map)
{
    if (!m_instance)
    {
        m_instance = new AISnake(mp, snake, map);
    }
    return m_instance;
}

void AISnake::delInstance()
{
    if (m_instance)
    {
        delete m_instance;
        m_instance = nullptr;
    }
}